<!doctype html>
<html lang="en-us">
<head>

    <meta charset="utf-8">
    <meta name="generator" content="Hugo 0.59.1" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>短信注册和微信登录的实现 | 林贤钦</title>
    <meta property="og:title" content="短信注册和微信登录的实现 - 林贤钦">
    <meta property="og:type" content="article">
        
    <meta property="article:published_time" content="2020-04-20T21:11:20&#43;08:00">
        
        
    <meta property="article:modified_time" content="2020-04-20T21:11:20&#43;08:00">
        
    <meta name="Keywords" content="java,博客,项目管理,软件架构,公众号,小程序">
    <meta name="description" content="短信注册和微信登录的实现">
        
    <meta name="author" content="林贤钦">
    <meta property="og:url" content="http://linxianqin.gitee.io/post/%E7%9F%AD%E4%BF%A1%E6%B3%A8%E5%86%8C%E5%92%8C%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E7%9A%84%E5%AE%9E%E7%8E%B0/">
    <link rel="shortcut icon" href="/img/favicon.ico" type="image/x-icon">

    <link rel="stylesheet" href="/css/normalize.css">
    
        <link rel="stylesheet" href="/css/prism.css">
    
    <link rel="stylesheet" href="/css/style.css">
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

    


    
    
</head>

<body>
<header id="header" class="clearfix">
	<div class="container">
        <div class="col-group">
            <div class="site-name ">
                
                    <a id="logo" href="http://linxianqin.gitee.io">
                        林贤钦
                    </a>
                
                <p class="description">专注于Java、微信小程序、移动互联网、项目管理、软件架构</p>
            </div>
            <div>
                <nav id="nav-menu" class="clearfix">
                    <a class="current" href="http://linxianqin.gitee.io">首页</a>
                    
                    <a  href="http://linxianqin.gitee.io/archives/" title="归档">归档</a>
                    
                    <a  href="http://linxianqin.gitee.io/about/" title="关于">关于</a>
                    
                </nav>
            </div>
        </div>
    </div>
</header>


<div id="body">
        
        
    <div class="container">
        <div class="col-group">

            <div class="col-8" id="main">
                <div class="res-cons">
                    <article class="post">
                        <header>
                            <h1 class="post-title">短信注册和微信登录的实现</h1>
                        </header>
                        <date class="post-meta meta-date">
                            2020年4月20日
                        </date>
                        
                        <div class="post-meta">
                            <span>|</span>
                            
                                <span class="meta-category"><a href="http://linxianqin.gitee.io/categories/java">java</a></span>
                            
                                <span class="meta-category"><a href="http://linxianqin.gitee.io/categories/%E9%98%BF%E9%87%8C%E4%BA%91">阿里云</a></span>
                            
                        </div>
                        
                        
                        <div class="post-meta">
                            <span id="busuanzi_container_page_pv">|<span id="busuanzi_value_page_pv"></span><span> 阅读</span></span>
                        </div>
                        
                        
                        <div class="post-content">
							<nav id="TableOfContents">
<ul>
<li><a href="#短信注册和微信登录的实现">短信注册和微信登录的实现</a>
<ul>
<li><a href="#一-阿里云短信服务">一、阿里云短信服务</a>
<ul>
<li><a href="#1-准备-开通阿里云短信服务">(1)  准备：开通阿里云短信服务</a></li>
<li><a href="#2-在pom中引入依赖">(2)  在pom中引入依赖</a></li>
<li><a href="#3-编写controller-根据手机号发送短信">(3)  编写controller，根据手机号发送短信</a></li>
<li><a href="#4-在service实现方法">(4) 在service实现方法</a></li>
</ul></li>
<li><a href="#注-以上就是发送验证码的过程-下面为注册过程">注：以上就是发送验证码的过程，下面为注册过程</a>
<ul>
<li><a href="#1-controller层">1、controller层</a></li>
</ul></li>
</ul></li>
<li><a href="#二-微信登录的实现">二、微信登录的实现</a>
<ul>
<li><a href="#一-准备工作"><strong>一、准备工作</strong></a>
<ul>
<li><a href="#1-注册">1、注册</a></li>
<li><a href="#2-邮箱激活">2、邮箱激活</a></li>
<li><a href="#3-完善开发者资料">3、完善开发者资料</a></li>
<li><a href="#4-开发者资质认证">4、开发者资质认证</a></li>
<li><a href="#5-创建网站应用">5、创建网站应用</a></li>
<li><a href="#6-熟悉微信登录流程">6、熟悉微信登录流程</a></li>
</ul></li>
<li><a href="#二-后端开发">二、后端开发</a>
<ul>
<li><a href="#1-添加配置">1、添加配置</a></li>
</ul></li>
<li><a href="#2-创建常量类"><strong>2、创建常量类</strong></a>
<ul>
<li><a href="#3-创建controller">3、创建controller</a></li>
<li><a href="#4-业务层">4、业务层</a></li>
</ul></li>
</ul></li>
</ul>
</nav>
                            

<h1 id="短信注册和微信登录的实现">短信注册和微信登录的实现</h1>

<p>短信发送过程，和微信发送过程，大多都是差不多的，改动不大，也没什么好说的，很简单，代码也固定，下面就是我整里的过程</p>

<h2 id="一-阿里云短信服务">一、阿里云短信服务</h2>

<p>帮助文档：</p>

<p><a href="https://help.aliyun.com/product/44282.html?spm=5176.10629532.0.0.38311cbeYzBm73">https://help.aliyun.com/product/44282.html?spm=5176.10629532.0.0.38311cbeYzBm73</a></p>

<h3 id="1-准备-开通阿里云短信服务">(1)  准备：开通阿里云短信服务</h3>

<p>添加  签名管理与模板管理</p>

<p><strong>选择 国内消息 - 模板管理 - 添加模板</strong></p>

<p><strong>点击 添加模板，进入到添加页面，输入模板信息</strong></p>

<p><strong>点击提交，等待审核，审核通过后可以使用</strong></p>

<p><strong>点击添加签名，进入添加页面，填入相关信息注意：签名要写的有实际意义</strong></p>

<p><strong>点击提交，等待审核，审核通过后可以使</strong></p>

<h3 id="2-在pom中引入依赖">(2)  在pom中引入依赖</h3>

<pre><code class="language-xml">&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.alibaba&lt;/groupId&gt;
        &lt;artifactId&gt;fastjson&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.aliyun&lt;/groupId&gt;
        &lt;artifactId&gt;aliyun-java-sdk-core&lt;/artifactId&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;
</code></pre>

<h3 id="3-编写controller-根据手机号发送短信">(3)  编写controller，根据手机号发送短信</h3>

<pre><code class="language-java">@RestController
@RequestMapping(&quot;/edumsm/msm&quot;)
@CrossOrigin
public class MsmController {
    @Autowired
    private MsmService msmService;

    //发送短信的方法
    @GetMapping(&quot;send/{phone}&quot;)
    public R sendMsm(@PathVariable String phone){
        return  msmService.sentByPhone(phone);
    }
}
</code></pre>

<h3 id="4-在service实现方法">(4) 在service实现方法</h3>

<pre><code class="language-java">@Service
public class MsmServiceImpl implements MsmService {
    @Autowired
    private RedisTemplate&lt;String,String&gt; redisTemplate;
    @Override
    public R sentByPhone(String phone) {
        //生成随机值,传递给阿里云
        String code = RandomUtil.getSixBitRandom();
        Map&lt;String,Object&gt; param = new HashMap&lt;&gt;();
        param.put(&quot;code&quot;,code);
        //调用service发送短信的方法
        boolean isSend =send(param,phone);
        if (isSend){
            //发送成功，把发送成功验证码放到redis里面
            //设置有效时间
            redisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);
            return R.ok();
        }else{
            return R.error().message(&quot;短信发送失败&quot;);
        }
    }

    //发送短信的方法
    @Override
    public boolean send(Map&lt;String, Object&gt; param, String phone) {
        if(StringUtils.isEmpty(phone)) return false;

        DefaultProfile profile =
                DefaultProfile.getProfile(&quot;default&quot;, &quot;阿里云的个人key_id&quot;, &quot;阿里云的个人密钥&quot;);
        IAcsClient client = new DefaultAcsClient(profile);

        //设置相关固定的参数
        CommonRequest request = new CommonRequest();
        //request.setProtocol(ProtocolType.HTTPS);
        request.setMethod(MethodType.POST);
        request.setDomain(&quot;dysmsapi.aliyuncs.com&quot;);
        request.setVersion(&quot;2017-05-25&quot;);
        request.setAction(&quot;SendSms&quot;);

        //设置发送相关的参数
        request.putQueryParameter(&quot;PhoneNumbers&quot;,phone); //手机号
        request.putQueryParameter(&quot;SignName&quot;,&quot;申请阿里云的签名名称&quot;); 
        request.putQueryParameter(&quot;TemplateCode&quot;,&quot;申请阿里云的模板code&quot;); 
        request.putQueryParameter(&quot;TemplateParam&quot;, JSONObject.toJSONString(param)); //验证码数据，转换json数据传递
        try {
            //最终发送
            CommonResponse response = client.getCommonResponse(request);
            boolean success = response.getHttpResponse().isSuccess();
            return success;
        }catch(Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}
</code></pre>

<p>(5)生成验证码工具类</p>

<pre><code class="language-java">/**
 * 获取随机数
 */
public class RandomUtil {

	private static final Random random = new Random();

	private static final DecimalFormat fourdf = new DecimalFormat(&quot;0000&quot;);

	private static final DecimalFormat sixdf = new DecimalFormat(&quot;000000&quot;);

	public static String getFourBitRandom() {
		return fourdf.format(random.nextInt(10000));
	}

	public static String getSixBitRandom() {
		return sixdf.format(random.nextInt(1000000));
	}

	/**
	 * 给定数组，抽取n个数据
	 * @param list
	 * @param n
	 * @return
	 */
	public static ArrayList getRandom(List list, int n) {
		Random random = new Random();
		HashMap&lt;Object, Object&gt; hashMap = new HashMap&lt;Object, Object&gt;();
		// 生成随机数字并存入HashMap
		for (int i = 0; i &lt; list.size(); i++) {
			int number = random.nextInt(100) + 1;
			hashMap.put(number, i);
		}
		// 从HashMap导入数组
		Object[] robjs = hashMap.values().toArray();
		ArrayList r = new ArrayList();
		// 遍历数组并打印数据
		for (int i = 0; i &lt; n; i++) {
			r.add(list.get((int) robjs[i]));
			System.out.print(list.get((int) robjs[i]) + &quot;\t&quot;);
		}
		System.out.print(&quot;\n&quot;);
		return r;
	}
}
</code></pre>

<h2 id="注-以上就是发送验证码的过程-下面为注册过程">注：以上就是发送验证码的过程，下面为注册过程</h2>

<h3 id="1-controller层">1、controller层</h3>

<pre><code class="language-java">@ApiOperation(value = &quot;会员注册&quot;)
@PostMapping(&quot;register&quot;)
public R register(@RequestBody RegisterInfoVo registerInfoVo){
    log.info(&quot;注册的用户信息&quot;+registerInfoVo);
    memberService.register(registerInfoVo);
    return R.ok();
}
</code></pre>

<p>2、service层</p>

<pre><code class="language-java">/**
 * 会员注册
 * @param registerInfoVo
 */
@Override
public void register(RegisterInfoVo registerInfoVo) {
    //获取注册信息，进行校验
    String mobile = registerInfoVo.getMobile();
    String nickname = registerInfoVo.getNickname();
    String password = registerInfoVo.getPassword();
    String code = registerInfoVo.getCode();
    //校验参数
    if(StringUtils.isEmpty(mobile) ||
       StringUtils.isEmpty(mobile) ||
       StringUtils.isEmpty(password) ||
       StringUtils.isEmpty(code)) {
        throw new SuperCourseException(ResultCode.ERROR,&quot;注册信息不能为空，请重新输入&quot;);
    }
    //校验校验验证码
    //从redis获取发送的验证码
    String redisCode = redisTemplate.opsForValue().get(mobile);
    log.info(&quot;redis中的验证码：&quot;+redisCode);
    log.info(&quot;用户输入的验证码：&quot;+code);
    if (!code.equals(redisCode)){
        throw new SuperCourseException(ResultCode.ERROR,&quot;验证码不正确！&quot;);
    }
    //查询数据库中是否存在相同的手机号码
    QueryWrapper&lt;User&gt; wrapper = new QueryWrapper&lt;&gt;();
    wrapper.eq(&quot;mobile&quot;,mobile);
    Integer count = baseMapper.selectCount(wrapper);
    if(count &gt; 0) {
        throw new SuperCourseException(ResultCode.ERROR, &quot;手机号码已存在！&quot;);
    }
    //添加注册信息到数据库
    User user = new User();
    user.setNickname(nickname);
    user.setMobile(mobile);
    user.setPassword(MD5.encrypt(password));
    user.setAvatar(Avatar.AVATAR);
    System.out.println(user);
    baseMapper.insert(user);
}
</code></pre>

<h1 id="二-微信登录的实现">二、微信登录的实现</h1>

<p>微信登录步骤都是死的，没上面好说的，我也没有申请，要企业相关资料才可以，我是用别人的几个信息，来进行本地式微信登录，只能重定向到本地，因为这个账户的服务器写好，重定向到本地特定的接口，在实际中，步骤也都差不多，只是修改重定向的url</p>

<h2 id="一-准备工作"><strong>一、准备工作</strong></h2>

<p><a href="https://open.weixin.qq.com">https://open.weixin.qq.com</a></p>

<h3 id="1-注册">1、注册</h3>

<h3 id="2-邮箱激活">2、邮箱激活</h3>

<h3 id="3-完善开发者资料">3、完善开发者资料</h3>

<h3 id="4-开发者资质认证">4、开发者资质认证</h3>

<p>准备营业执照，1-2个工作日审批、300元</p>

<h3 id="5-创建网站应用">5、创建网站应用</h3>

<p>提交审核，7个工作日审批</p>

<h3 id="6-熟悉微信登录流程">6、熟悉微信登录流程</h3>

<p>参考文档：<a href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&amp;t=resource/res_list&amp;verify=1&amp;id=open1419316505&amp;token=e547653f995d8f402704d5cb2945177dc8aa4e7e&amp;lang=zh_CN">https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&amp;t=resource/res_list&amp;verify=1&amp;id=open1419316505&amp;token=e547653f995d8f402704d5cb2945177dc8aa4e7e&amp;lang=zh_CN</a></p>

<h2 id="二-后端开发">二、后端开发</h2>

<p>1、添加依赖</p>

<pre><code class="language-xml"> &lt;!--httpclient--&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.apache.httpcomponents&lt;/groupId&gt;
    &lt;artifactId&gt;httpclient&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;!--commons-io--&gt;
&lt;dependency&gt;
   &lt;groupId&gt;commons-io&lt;/groupId&gt;
   &lt;artifactId&gt;commons-io&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;!--gson--&gt;
&lt;dependency&gt;
    &lt;groupId&gt;com.google.code.gson&lt;/groupId&gt;
    &lt;artifactId&gt;gson&lt;/artifactId&gt;
&lt;/dependency&gt;
</code></pre>

<h3 id="1-添加配置">1、添加配置</h3>

<p>application.properties添加相关配置信息</p>

<pre><code class="language-properties"># 微信开放平台 appid
wx.open.app_id=你的appid
# 微信开放平台 appsecret
wx.open.app_secret=你的appsecret
# 微信开放平台 重定向url
wx.open.redirect_url=http://你的服务器名称/api/ucenter/wx/callback
</code></pre>

<h2 id="2-创建常量类"><strong>2、创建常量类</strong></h2>

<p>创建util包，创建ConstantPropertiesUtil.java常量类</p>

<pre><code class="language-java">@Component
public class ConstantWxUtils implements InitializingBean {

    @Value(&quot;${wx.open.app_id}&quot;)
    private String appId;

    @Value(&quot;${wx.open.app_secret}&quot;)
    private String appSecret;

    @Value(&quot;${wx.open.redirect_url}&quot;)
    private String redirectUrl;

    public static String WX_OPEN_APP_ID;
    public static String WX_OPEN_APP_SECRET;
    public static String WX_OPEN_REDIRECT_URL;

    @Override
    public void afterPropertiesSet() throws Exception {
        WX_OPEN_APP_ID = appId;
        WX_OPEN_APP_SECRET = appSecret;
        WX_OPEN_REDIRECT_URL = redirectUrl;
    }
}
</code></pre>

<h3 id="3-创建controller">3、创建controller</h3>

<pre><code class="language-java">@CrossOrigin
@Controller//注意这里没有配置 @RestController
@RequestMapping(&quot;/api/ucenter/wx&quot;)
public class WxApiController {

    @Autowired
    private UserService userService;
    //1 生成微信扫描二维码
    @GetMapping(&quot;login&quot;)
    public String getWxCode() {
        //固定地址，后面拼接参数
//        String url = &quot;https://open.weixin.qq.com/&quot; +
//                &quot;connect/qrconnect?appid=&quot;+ ConstantWxUtils.WX_OPEN_APP_ID+&quot;&amp;response_type=code&quot;;

        // 微信开放平台授权baseUrl  %s相当于?代表占位符
        String baseUrl = &quot;https://open.weixin.qq.com/connect/qrconnect&quot; +
                &quot;?appid=%s&quot; +
                &quot;&amp;redirect_uri=%s&quot; +
                &quot;&amp;response_type=code&quot; +
                &quot;&amp;scope=snsapi_login&quot; +
                &quot;&amp;state=%s&quot; +
                &quot;#wechat_redirect&quot;;

        //对redirect_url进行URLEncoder编码
        String redirectUrl = ConstantWxUtils.WX_OPEN_REDIRECT_URL;
        try {
            redirectUrl = URLEncoder.encode(redirectUrl, &quot;utf-8&quot;);
        }catch(Exception e) {
        }

        //设置%s里面值
        String url = String.format(
                baseUrl,
                ConstantWxUtils.WX_OPEN_APP_ID,
                redirectUrl,
                &quot;superCourse&quot;
        );

        //重定向到请求微信地址里面
        return &quot;redirect:&quot;+url;
    }

    @GetMapping(&quot;callback&quot;)
    public String callback(String code, String state) {
        try {
            //1 获取code值，临时票据，类似于验证码
            //2 拿着code请求 微信固定的地址，得到两个值 accsess_token 和 openid
            String baseAccessTokenUrl = &quot;https://api.weixin.qq.com/sns/oauth2/access_token&quot; +
                    &quot;?appid=%s&quot; +
                    &quot;&amp;secret=%s&quot; +
                    &quot;&amp;code=%s&quot; +
                    &quot;&amp;grant_type=authorization_code&quot;;
            //拼接三个参数 ：id  秘钥 和 code值
            String accessTokenUrl = String.format(
                    baseAccessTokenUrl,
                    ConstantWxUtils.WX_OPEN_APP_ID,
                    ConstantWxUtils.WX_OPEN_APP_SECRET,
                    code
            );
            //请求这个拼接好的地址，得到返回两个值 accsess_token 和 openid
            //使用httpclient发送请求，得到返回结果
            String accessTokenInfo = HttpClientUtils.get(accessTokenUrl);

            //从accessTokenInfo字符串获取出来两个值 accsess_token 和 openid
            //把accessTokenInfo字符串转换map集合，根据map里面key获取对应值
            //使用json转换工具 Gson
            Gson gson = new Gson();
            HashMap mapAccessToken = gson.fromJson(accessTokenInfo, HashMap.class);
            String access_token = (String)mapAccessToken.get(&quot;access_token&quot;);
            String openid = (String)mapAccessToken.get(&quot;openid&quot;);

            //把扫描人信息添加数据库里面
            //判断数据表里面是否存在相同微信信息，根据openid判断
            User user = UserService.getUserByOpenId(openid);
            if(user == null) {//user是空，表没有相同微信数据，进行添加

                //3 拿着得到accsess_token 和 openid，再去请求微信提供固定的地址，获取到扫描人信息
                //访问微信的资源服务器，获取用户信息
                String baseUserInfoUrl = &quot;https://api.weixin.qq.com/sns/userinfo&quot; +
                        &quot;?access_token=%s&quot; +
                        &quot;&amp;openid=%s&quot;;
                //拼接两个参数
                String userInfoUrl = String.format(
                        baseUserInfoUrl,
                        access_token,
                        openid
                );
                //发送请求
                String userInfo = HttpClientUtils.get(userInfoUrl);
                //获取返回userinfo字符串扫描人信息
                HashMap userInfoMap = gson.fromJson(userInfo, HashMap.class);
                String nickname = (String)userInfoMap.get(&quot;nickname&quot;);//昵称
                String headimgurl = (String)userInfoMap.get(&quot;headimgurl&quot;);//头像

                user = new UcenterMember();
                user.setOpenid(openid);
                user.setNickname(nickname);
                user.setAvatar(headimgurl);
                userService.save(member);
            }
            //使用jwt根据member对象生成token字符串
            String jwtToken = JwtUtils.getJwtToken(user.getId(), user.getNickname());
            //最后：返回首页面，通过路径传递token字符串
            return &quot;redirect:http://localhost:3000?token=&quot;+jwtToken;
        }catch(Exception e) {
            throw new SuperCourseException(ResultCode.ERROR,&quot;登录失败&quot;);
        }
    }
}
</code></pre>

<h3 id="4-业务层">4、业务层</h3>

<p>业务接口：UserService.java</p>

<pre><code class="language-java">@Override
public User getUserByOpenId(String openid) {
    QueryWrapper&lt;UcenterMember&gt; queryWrapper = new QueryWrapper&lt;&gt;();
    queryWrapper.eq(&quot;openid&quot;, openid);
    UcenterMember member = baseMapper.selectOne(queryWrapper);
    return member;
}
</code></pre>

<p>HttpClientUtils工具类</p>

<pre><code class="language-java">import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 *  依赖的jar包有：commons-lang-2.6.jar、httpclient-4.3.2.jar、httpcore-4.3.1.jar、commons-io-2.4.jar
 *
 */
public class HttpClientUtils {

	public static final int connTimeout=10000;
	public static final int readTimeout=10000;
	public static final String charset=&quot;UTF-8&quot;;
	private static HttpClient client = null;

	static {
		PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
		cm.setMaxTotal(128);
		cm.setDefaultMaxPerRoute(128);
		client = HttpClients.custom().setConnectionManager(cm).build();
	}

	public static String postParameters(String url, String parameterStr) throws ConnectTimeoutException, SocketTimeoutException, Exception{
		return post(url,parameterStr,&quot;application/x-www-form-urlencoded&quot;,charset,connTimeout,readTimeout);
	}

	public static String postParameters(String url, String parameterStr,String charset, Integer connTimeout, Integer readTimeout) throws ConnectTimeoutException, SocketTimeoutException, Exception{
		return post(url,parameterStr,&quot;application/x-www-form-urlencoded&quot;,charset,connTimeout,readTimeout);
	}

	public static String postParameters(String url, Map&lt;String, String&gt; params) throws ConnectTimeoutException,
			SocketTimeoutException, Exception {
		return postForm(url, params, null, connTimeout, readTimeout);
	}

	public static String postParameters(String url, Map&lt;String, String&gt; params, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
			SocketTimeoutException, Exception {
		return postForm(url, params, null, connTimeout, readTimeout);
	}

	public static String get(String url) throws Exception {
		return get(url, charset, null, null);
	}

	public static String get(String url, String charset) throws Exception {
		return get(url, charset, connTimeout, readTimeout);
	}

	/**
	 * 发送一个 Post 请求, 使用指定的字符集编码.
	 *
	 * @param url
	 * @param body RequestBody
	 * @param mimeType 例如 application/xml &quot;application/x-www-form-urlencoded&quot; a=1&amp;b=2&amp;c=3
	 * @param charset 编码
	 * @param connTimeout 建立链接超时时间,毫秒.
	 * @param readTimeout 响应超时时间,毫秒.
	 * @return ResponseBody, 使用指定的字符集编码.
	 * @throws ConnectTimeoutException 建立链接超时异常
	 * @throws SocketTimeoutException  响应超时
	 * @throws Exception
	 */
	public static String post(String url, String body, String mimeType,String charset, Integer connTimeout, Integer readTimeout)
			throws ConnectTimeoutException, SocketTimeoutException, Exception {
		HttpClient client = null;
		HttpPost post = new HttpPost(url);
		String result = &quot;&quot;;
		try {
			if (StringUtils.isNotBlank(body)) {
				HttpEntity entity = new StringEntity(body, ContentType.create(mimeType, charset));
				post.setEntity(entity);
			}
			// 设置参数
			Builder customReqConf = RequestConfig.custom();
			if (connTimeout != null) {
				customReqConf.setConnectTimeout(connTimeout);
			}
			if (readTimeout != null) {
				customReqConf.setSocketTimeout(readTimeout);
			}
			post.setConfig(customReqConf.build());

			HttpResponse res;
			if (url.startsWith(&quot;https&quot;)) {
				// 执行 Https 请求.
				client = createSSLInsecureClient();
				res = client.execute(post);
			} else {
				// 执行 Http 请求.
				client = HttpClientUtils.client;
				res = client.execute(post);
			}
			result = IOUtils.toString(res.getEntity().getContent(), charset);
		} finally {
			post.releaseConnection();
			if (url.startsWith(&quot;https&quot;) &amp;&amp; client != null&amp;&amp; client instanceof CloseableHttpClient) {
				((CloseableHttpClient) client).close();
			}
		}
		return result;
	}


	/**
	 * 提交form表单
	 *
	 * @param url
	 * @param params
	 * @param connTimeout
	 * @param readTimeout
	 * @return
	 * @throws ConnectTimeoutException
	 * @throws SocketTimeoutException
	 * @throws Exception
	 */
	public static String postForm(String url, Map&lt;String, String&gt; params, Map&lt;String, String&gt; headers, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
			SocketTimeoutException, Exception {

		HttpClient client = null;
		HttpPost post = new HttpPost(url);
		try {
			if (params != null &amp;&amp; !params.isEmpty()) {
				List&lt;NameValuePair&gt; formParams = new ArrayList&lt;NameValuePair&gt;();
				Set&lt;Entry&lt;String, String&gt;&gt; entrySet = params.entrySet();
				for (Entry&lt;String, String&gt; entry : entrySet) {
					formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
				}
				UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, Consts.UTF_8);
				post.setEntity(entity);
			}

			if (headers != null &amp;&amp; !headers.isEmpty()) {
				for (Entry&lt;String, String&gt; entry : headers.entrySet()) {
					post.addHeader(entry.getKey(), entry.getValue());
				}
			}
			// 设置参数
			Builder customReqConf = RequestConfig.custom();
			if (connTimeout != null) {
				customReqConf.setConnectTimeout(connTimeout);
			}
			if (readTimeout != null) {
				customReqConf.setSocketTimeout(readTimeout);
			}
			post.setConfig(customReqConf.build());
			HttpResponse res = null;
			if (url.startsWith(&quot;https&quot;)) {
				// 执行 Https 请求.
				client = createSSLInsecureClient();
				res = client.execute(post);
			} else {
				// 执行 Http 请求.
				client = HttpClientUtils.client;
				res = client.execute(post);
			}
			return IOUtils.toString(res.getEntity().getContent(), &quot;UTF-8&quot;);
		} finally {
			post.releaseConnection();
			if (url.startsWith(&quot;https&quot;) &amp;&amp; client != null
					&amp;&amp; client instanceof CloseableHttpClient) {
				((CloseableHttpClient) client).close();
			}
		}
	}




	/**
	 * 发送一个 GET 请求
	 *
	 * @param url
	 * @param charset
	 * @param connTimeout  建立链接超时时间,毫秒.
	 * @param readTimeout  响应超时时间,毫秒.
	 * @return
	 * @throws ConnectTimeoutException   建立链接超时
	 * @throws SocketTimeoutException   响应超时
	 * @throws Exception
	 */
	public static String get(String url, String charset, Integer connTimeout,Integer readTimeout)
			throws ConnectTimeoutException,SocketTimeoutException, Exception {

		HttpClient client = null;
		HttpGet get = new HttpGet(url);
		String result = &quot;&quot;;
		try {
			// 设置参数
			Builder customReqConf = RequestConfig.custom();
			if (connTimeout != null) {
				customReqConf.setConnectTimeout(connTimeout);
			}
			if (readTimeout != null) {
				customReqConf.setSocketTimeout(readTimeout);
			}
			get.setConfig(customReqConf.build());

			HttpResponse res = null;

			if (url.startsWith(&quot;https&quot;)) {
				// 执行 Https 请求.
				client = createSSLInsecureClient();
				res = client.execute(get);
			} else {
				// 执行 Http 请求.
				client = HttpClientUtils.client;
				res = client.execute(get);
			}

			result = IOUtils.toString(res.getEntity().getContent(), charset);
		} finally {
			get.releaseConnection();
			if (url.startsWith(&quot;https&quot;) &amp;&amp; client != null &amp;&amp; client instanceof CloseableHttpClient) {
				((CloseableHttpClient) client).close();
			}
		}
		return result;
	}


	/**
	 * 从 response 里获取 charset
	 *
	 * @param ressponse
	 * @return
	 */
	@SuppressWarnings(&quot;unused&quot;)
	private static String getCharsetFromResponse(HttpResponse ressponse) {
		// Content-Type:text/html; charset=GBK
		if (ressponse.getEntity() != null  &amp;&amp; ressponse.getEntity().getContentType() != null &amp;&amp; ressponse.getEntity().getContentType().getValue() != null) {
			String contentType = ressponse.getEntity().getContentType().getValue();
			if (contentType.contains(&quot;charset=&quot;)) {
				return contentType.substring(contentType.indexOf(&quot;charset=&quot;) + 8);
			}
		}
		return null;
	}



	/**
	 * 创建 SSL连接
	 * @return
	 * @throws GeneralSecurityException
	 */
	private static CloseableHttpClient createSSLInsecureClient() throws GeneralSecurityException {
		try {
			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
				public boolean isTrusted(X509Certificate[] chain,String authType) throws CertificateException {
					return true;
				}
			}).build();

			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {

				@Override
				public boolean verify(String arg0, SSLSession arg1) {
					return true;
				}

				@Override
				public void verify(String host, SSLSocket ssl)
						throws IOException {
				}

				@Override
				public void verify(String host, X509Certificate cert)
						throws SSLException {
				}

				@Override
				public void verify(String host, String[] cns,
								   String[] subjectAlts) throws SSLException {
				}

			});

			return HttpClients.custom().setSSLSocketFactory(sslsf).build();

		} catch (GeneralSecurityException e) {
			throw e;
		}
	}

	public static void main(String[] args) {
		try {
			String str= post(&quot;https://localhost:443/ssl/test.shtml&quot;,&quot;name=12&amp;page=34&quot;,&quot;application/x-www-form-urlencoded&quot;, &quot;UTF-8&quot;, 10000, 10000);
			//String str= get(&quot;https://localhost:443/ssl/test.shtml?name=12&amp;page=34&quot;,&quot;GBK&quot;);
            /*Map&lt;String,String&gt; map = new HashMap&lt;String,String&gt;();
            map.put(&quot;name&quot;, &quot;111&quot;);
            map.put(&quot;page&quot;, &quot;222&quot;);
            String str= postForm(&quot;https://localhost:443/ssl/test.shtml&quot;,map,null, 10000, 10000);*/
			System.out.println(str);
		} catch (ConnectTimeoutException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SocketTimeoutException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
</code></pre>

                        </div>
						 
                        
<div class="post-archive">
    <ul class="post-copyright">
        <li><strong>原文作者：</strong><a rel="author" href="http://linxianqin.gitee.io">林贤钦</a></li>
        <li style="word-break:break-all"><strong>原文链接：</strong><a href="http://linxianqin.gitee.io/post/%E7%9F%AD%E4%BF%A1%E6%B3%A8%E5%86%8C%E5%92%8C%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E7%9A%84%E5%AE%9E%E7%8E%B0/">http://linxianqin.gitee.io/post/%E7%9F%AD%E4%BF%A1%E6%B3%A8%E5%86%8C%E5%92%8C%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E7%9A%84%E5%AE%9E%E7%8E%B0/</a></li>
        <li><strong>版权声明：</strong>本作品采用<a rel="license" href="https://linxianqin.gitee.io">知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议</a>进行许可，非商业转载请注明出处（作者，原文链接），商业转载请联系作者获得授权。</li>
    </ul>
</div>
<br/>



                        

<div class="post-archive">
    <h2>See Also</h2>
    <ul class="listing">
        
        <li><a href="/post/OAuth2.0%E8%AE%A4%E8%AF%81%E6%8E%88%E6%9D%83%E5%8D%95%E7%82%B9%E7%99%BB%E5%BD%95/">OAuth2.0认证授权单点登录</a></li>
        
        <li><a href="/post/%E9%98%BF%E9%87%8C%E4%BA%91%E8%A7%86%E9%A2%91%E7%82%B9%E6%92%AD%E6%9C%8D%E5%8A%A1/">阿里云视频点播服务前后端实现</a></li>
        
        <li><a href="/post/%E9%98%BF%E9%87%8C%E4%BA%91EasyExcel%E5%AE%9E%E7%8E%B0%E5%90%8E%E7%AB%AF%E5%AF%B9Excel%E7%9A%84%E8%AF%BB%E5%86%99%E6%93%8D%E4%BD%9C/">使用阿里云EasyExcel实现后端对Excel的读写操作</a></li>
        
        <li><a href="/post/%E9%98%BF%E9%87%8C%E4%BA%91oss%E5%AF%B9%E8%B1%A1%E5%AD%98%E5%82%A8%E6%9C%8D%E5%8A%A1%E5%AE%9E%E7%8E%B0/">阿里云oss对象存储服务实现</a></li>
        
        <li><a href="/post/Nacos%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83/">Nacos服务注册中心</a></li>
        
    </ul>
</div>


                        <div class="post-meta meta-tags">
                            
                            <ul class="clearfix">
                                
                                <li><a href="http://linxianqin.gitee.io/tags/%E9%98%BF%E9%87%8C%E4%BA%91">阿里云</a></li>
                                
                                <li><a href="http://linxianqin.gitee.io/tags/java">java</a></li>
                                
                            </ul>
                            
                        </div>
                    </article>
                    
    

    
    
    <div class="post bg-white">
      <script src="https://utteranc.es/client.js"
            repo= "757610938/hugo-blogs-utterances"
            issue-term="pathname"
            theme="github-light"
            crossorigin="anonymous"
            async>
      </script>
    </div>
    
                </div>
            </div>
            <div id="secondary">
    <section class="widget">
        <form id="search" action="//www.google.com/search" method="get" accept-charset="utf-8" target="_blank" _lpchecked="1">
      
      <input type="text" name="q" maxlength="20" placeholder="Search">
      <input type="hidden" name="sitesearch" value="http://linxianqin.gitee.io">
      <button type="submit" class="submit icon-search"></button>
</form>
    </section>
    
    <section class="widget">
        <h3 class="widget-title">最近文章</h3>
<ul class="widget-list">
    
    <li>
        <a href="http://linxianqin.gitee.io/post/java-%E5%8F%8D%E5%B0%84/" title="Java 反射">Java 反射</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/java-%E9%93%BE%E8%A1%A8/" title="Java 链表">Java 链表</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/%E7%9F%AD%E4%BF%A1%E6%B3%A8%E5%86%8C%E5%92%8C%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E7%9A%84%E5%AE%9E%E7%8E%B0/" title="短信注册和微信登录的实现">短信注册和微信登录的实现</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/OAuth2.0%E8%AE%A4%E8%AF%81%E6%8E%88%E6%9D%83%E5%8D%95%E7%82%B9%E7%99%BB%E5%BD%95/" title="OAuth2.0认证授权单点登录">OAuth2.0认证授权单点登录</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/Nacos%E6%9C%8D%E5%8A%A1%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83/" title="Nacos服务注册中心">Nacos服务注册中心</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/SpringCloud%E5%BE%AE%E6%9C%8D%E5%8A%A1/" title="SpringCloud微服务">SpringCloud微服务</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/%E9%98%BF%E9%87%8C%E4%BA%91%E8%A7%86%E9%A2%91%E7%82%B9%E6%92%AD%E6%9C%8D%E5%8A%A1/" title="阿里云视频点播服务前后端实现">阿里云视频点播服务前后端实现</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/%E9%98%9F%E5%88%97/" title="队列">队列</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/%E7%A8%80%E7%96%8F%E6%95%B0%E7%BB%84/" title="稀疏数组">稀疏数组</a>
    </li>
    
    <li>
        <a href="http://linxianqin.gitee.io/post/%E9%98%BF%E9%87%8C%E4%BA%91EasyExcel%E5%AE%9E%E7%8E%B0%E5%90%8E%E7%AB%AF%E5%AF%B9Excel%E7%9A%84%E8%AF%BB%E5%86%99%E6%93%8D%E4%BD%9C/" title="使用阿里云EasyExcel实现后端对Excel的读写操作">使用阿里云EasyExcel实现后端对Excel的读写操作</a>
    </li>
    
</ul>
    </section>

    

    <section class="widget">
        <h3 class="widget-title">分类</h3>
<ul class="widget-list">
    
    <li><a href="http://linxianqin.gitee.io/categories/JWT/">JWT (2)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/hugo/">hugo (2)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/java/">java (18)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/java8/">java8 (1)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/springCloud/">springCloud (2)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/springSecurity/">springSecurity (4)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/vue/">vue (5)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/yml/">yml (1)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/">数据结构 (3)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/">软件测试 (1)</a></li>
    
    <li><a href="http://linxianqin.gitee.io/categories/%E9%98%BF%E9%87%8C%E4%BA%91/">阿里云 (4)</a></li>
    
</ul>
    </section>

    <section class="widget">
        <h3 class="widget-title">标签</h3>
<div class="tagcloud">
    
    <a href="http://linxianqin.gitee.io/tags/JWT/">JWT</a>
    
    <a href="http://linxianqin.gitee.io/tags/hugo/">hugo</a>
    
    <a href="http://linxianqin.gitee.io/tags/java/">java</a>
    
    <a href="http://linxianqin.gitee.io/tags/java8/">java8</a>
    
    <a href="http://linxianqin.gitee.io/tags/spring/">spring</a>
    
    <a href="http://linxianqin.gitee.io/tags/springBoot/">springBoot</a>
    
    <a href="http://linxianqin.gitee.io/tags/springCloud/">springCloud</a>
    
    <a href="http://linxianqin.gitee.io/tags/ssm/">ssm</a>
    
    <a href="http://linxianqin.gitee.io/tags/vue/">vue</a>
    
    <a href="http://linxianqin.gitee.io/tags/yml/">yml</a>
    
    <a href="http://linxianqin.gitee.io/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/">数据结构</a>
    
    <a href="http://linxianqin.gitee.io/tags/%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/">软件测试</a>
    
    <a href="http://linxianqin.gitee.io/tags/%E9%98%BF%E9%87%8C%E4%BA%91/">阿里云</a>
    
</div>
    </section>

    
<section class="widget">
    <h3 class="widget-title">友情链接</h3>
    <ul class="widget-list">
        
        <li>
            <a target="_blank" href="https://www.cnki.net" title="中国知网">中国知网</a>
        </li>
        
        <li>
            <a target="_blank" href="https://linxianqin.com" title="个人的另一个博客网站(国内加载慢)">个人的另一个博客网站(国内加载慢)</a>
        </li>
        
    </ul>
</section>


    <section class="widget">
        <h3 class="widget-title">其它</h3>
        <ul class="widget-list">
            <li><a href="http://linxianqin.gitee.io/index.xml">文章 RSS</a></li>
        </ul>
    </section>
</div>
        </div>
    </div>
</div>
<footer id="footer">
    <div class="container">
        &copy; 2020 <a href="http://linxianqin.gitee.io">林贤钦 By 林贤钦</a>.
        Powered by <a rel="nofollow noreferer noopener" href="https://gohugo.io" target="_blank">Hugo</a>.
        <a href="https://www.flysnow.org/" target="_blank">Theme</a> based on <a href="https://github.com/rujews/maupassant-hugo" target="_blank">maupassant</a>.
        
    </div>
</footer>


    
    <script type="text/javascript">
        
        (function () {
            $("pre code").parent().addClass("line-numbers")
        }());

        window.MathJax = {
            tex2jax: {
                inlineMath: [['$', '$']],
                processEscapes: true
                }
            };
    </script>
    <script type="text/javascript" src="/js/prism.js" async="true"></script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script>


<a id="rocket" href="#top"></a>
<script type="text/javascript" src="/js/totop.js?v=0.0.0" async=""></script>

<script type="application/javascript">
var doNotTrack = false;
if (!doNotTrack) {
	window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
	ga('create', 'GA ID', 'auto');
	
	ga('send', 'pageview');
}
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>



    <script type="text/javascript" src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" async></script>




</body>
</html>
